package entity

import (
	"src/protoMsg"
	"src/zeus/iserver"

	"src/zeus/logger"
)

// 脏属性分流器节点封装
type IPropsSyncContainer interface {
	ProsSyncInitProp(def *Def, interestSrvType uint8, subType string)
	ProsSyncInitProp2(def *Def, subType string)
	PackPropsSyncProps()
	PackPropsSaveProps() *protoMsg.PropBaseSyncList
	PackPropsAOIProps() *protoMsg.PropBaseSyncList
	PackPropsRoleProps() *protoMsg.PropBaseSyncList
	GetDirtyAOIMsg() *protoMsg.PropBaseSyncList
	GetDirtyMRoleMsg() *protoMsg.PropBaseSyncList
	ProsSyncDestroy()
}

// PropsSyncContainer 需要进行属性同步的部分
type PropsSyncContainer struct {
	IPropsContainer

	dirtyAOIProps   []*PropInfo
	dirtyMRoleProps []*PropInfo
	dirtySaveProps  []*PropInfo
	//需要同步给其他服务器的数据
	DirtySrvProps map[uint8][]*PropInfo

	DirtyAOIMsg   *protoMsg.PropBaseSyncList
	DirtyMRoleMsg *protoMsg.PropBaseSyncList
}

func NewPropsSyncContainer() *PropsSyncContainer {
	c := &PropsSyncContainer{}
	c.ProsSyncInit()
	return c
}

// Init 初始化
func (c *PropsSyncContainer) ProsSyncInit() {
	c.IPropsContainer = NewPropsContainer()
	c.IPropsContainer.AddDirtyPropSorter(EDPSorterTypeSync)
	c.IPropsContainer.AddDirtyPropSorter(EDPSorterTypeSave)
	c.dirtyAOIProps = make([]*PropInfo, 0, 10)
	c.dirtyMRoleProps = make([]*PropInfo, 0, 10)
	c.dirtySaveProps = make([]*PropInfo, 0, 10)
	c.DirtySrvProps = make(map[uint8][]*PropInfo)
}

// Init 初始化
func (c *PropsSyncContainer) ProsSyncDestroy() {
	c.IPropsContainer.DestroyProp()
	// c.dirtyAOIProps = nil
	// c.dirtyMRoleProps = nil
	// c.dirtySaveProps = nil
}

// ProsSyncInitProp 初始化属性列表
func (c *PropsSyncContainer) ProsSyncInitProp(def *Def, interestSrvType uint8, subType string) {
	if def == nil {
		logger.Error("ProsSyncInitProp def is nil")
		return
	}
	c.IPropsContainer.InitProp(def, interestSrvType, subType)
}

// ProsSyncInitProp2 初始化属性列表
func (c *PropsSyncContainer) ProsSyncInitProp2(def *Def, subType string) {
	c.IPropsContainer.InitProp2(def, subType)
}

// 获取AOI需要的差量属性更新
func (c *PropsSyncContainer) GetDirtyAOIMsg() *protoMsg.PropBaseSyncList {
	return c.DirtyAOIMsg
}

// 获取自身需要的差量属性更新
func (c *PropsSyncContainer) GetDirtyMRoleMsg() *protoMsg.PropBaseSyncList {
	return c.DirtyMRoleMsg
}

// 打包同步数据：给自己的，给AOI的，给其他服务器的
func (c *PropsSyncContainer) PackPropsSyncProps() {
	/*
		需要每次都生成数据，这样后面就不用再判空了。
		只需要判断成员数量
	*/
	c.DirtyAOIMsg = new(protoMsg.PropBaseSyncList)
	c.DirtyMRoleMsg = new(protoMsg.PropBaseSyncList)
	if c.GetDirtyPropSorter(EDPSorterTypeSync).ListCount() == 0 {

		// c.DirtySrvProps = make(map[uint8][]*PropInfo)
		return
	}
	c.HandlerSorterResultForeach(EDPSorterTypeSync, func(p *PropInfo) {
		//如果数据需要同步给别的服务器的话
		for _, s := range p.Def.InterestSrvs {
			if s == iserver.GetSrvInst().GetSaveType() {
				continue
			} else if s == p.Def.SaveSrvType {
				continue
			} else if s == p.Def.MainSrvType {
				continue
			}
			m := c.getDirtyProps(s)
			c.DirtySrvProps[s] = append(m, p)

		}
		if p.Def.IsClientInterest {
			c.dirtyAOIProps = append(c.dirtyAOIProps, p)
		}
		if p.Def.IsMRoleInterest { //fixed
			//非自己管理的属性 是不需要发送给自己的客户端的.
			if !(p.Def.SaveSrvType == iserver.GetSrvInst().GetSaveType() ||
				p.Def.MainSrvType == iserver.GetSrvInst().GetSaveType()) {
				logger.Debug(logger.LogKey_Prop, p.Def.Name, " 非本服务器 关心属性,不要给客户端下发属性.", p)
				return
			}
			if p.Def.Name == "PlayerGuildInfo" { //fixed log
				logger.Debug(logger.LogKey_Prop, "PlayerGuildInfo 本服务器 关心属性,给客户端下发属性.", p)
			}
			c.dirtyMRoleProps = append(c.dirtyMRoleProps, p)
			return
		}
	})

	if len(c.dirtyAOIProps) > 0 {
		c.DirtyAOIMsg = PackPropsToProtobuf(c.dirtyAOIProps)
		c.dirtyAOIProps = c.dirtyAOIProps[0:0]
	}
	if len(c.dirtyMRoleProps) > 0 {
		c.DirtyMRoleMsg = PackPropsToProtobuf(c.dirtyMRoleProps)
		c.dirtyMRoleProps = c.dirtyMRoleProps[0:0]
	}
}

func (c *PropsSyncContainer) PackPropsSaveProps() *protoMsg.PropBaseSyncList {
	if c.GetDirtyPropSorter(EDPSorterTypeSave).ListCount() == 0 {
		return nil
	}
	c.ForEachProp(func(p *PropInfo) {
		if p.Def.SaveSrvType == iserver.GetSrvInst().GetSaveType() {
			c.dirtySaveProps = append(c.dirtySaveProps, p)
		}
	})
	DirtySaveMsg := PackPropsToProtobuf(c.dirtySaveProps)
	c.dirtySaveProps = c.dirtySaveProps[0:0]
	return DirtySaveMsg
}

// 打包全量AOI数据
func (c *PropsSyncContainer) PackPropsAOIProps() *protoMsg.PropBaseSyncList {
	return PackProps(c, PackProp_AOI)
}

// 打包全量自己关心的数据
func (c *PropsSyncContainer) PackPropsRoleProps() *protoMsg.PropBaseSyncList {
	return PackProps(c, PackProp_Role)
}

// 获取目标服务器的脏数据
func (c *PropsSyncContainer) getDirtyProps(srvType uint8) []*PropInfo {
	m, ok := c.DirtySrvProps[srvType]
	if !ok {
		m = make([]*PropInfo, 0, 10)
		c.DirtySrvProps[srvType] = m
	}
	return m
}
